// vector.hpp
// A generic implementation of a vector data structure.
//
// Copyright (C) 2008  Maksim Sipos <msipos@mailc.net>
//
// This file is a part of the Ripe language project.
//
// Ripe is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

#ifndef R_VECTOR_HPP
#define R_VECTOR_HPP

#include "standard.hpp"
#include "util/exception.hpp"

// New vectors preallocate this much space.
#ifndef R_VECTOR_DEFAULT_SIZE
#define R_VECTOR_DEFAULT_SIZE 2
#endif

namespace Ripe{
  // Out of range error.
  class ErrorRange : public Exception {};

  template <class T>
  class Vector {
    public:
      // Construct an empty vector, but preallocate space for n elements.
      Vector(uint32_t n = R_VECTOR_DEFAULT_SIZE);

      // Construct a vector copy.
      Vector(Vector<T>* copy);

      // Deallocate the space in the Vector.
      ~Vector();

      // Append an element to the vector.
      void append(T element);

      // Pop an element from the end of the vector.
      T pop() throw(ErrorRange);

      // Get an element at location n in the vector.
      T operator[](uint32_t n) throw(ErrorRange);

      // Alias for [].
      T  get(uint32_t n) throw(ErrorRange);

      // Set an element at location n in the vector.
      void set(uint32_t n, T element) throw(ErrorRange);

      // Get the last element of the vector.
      T last() throw(ErrorRange);

      // Empty the vector.
      void clear() throw();

      // Size of the vector. (Read-only!)
      uint32_t size;

      // Set the size of the vector.
      void set_size(uint32_t new_size);

    private:
      // Check if the vector needs to be shrinked (reduced in size in
      // response to removing of the elements.
      inline void shrink();

      // Space for alloc_size many elements is allocated.
      uint32_t alloc_size;

      // Pointer to the actual data.
      T* data;
  };
}

#include "vector.cpp"

#endif // R_VECTOR_HPP
